﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Data;

namespace theeg.DependencyAnalysis.CommonAddin.Behaviors
{
    public class ViewSourceGroup
    {
        public readonly static IDictionary<string, ViewSourceGroup> Groups = new Dictionary<string, ViewSourceGroup>();
        private static readonly object GroupLock = new object();

        public static void AddToGroup(CollectionViewSource viewSource, string groupName)
        {
            lock (GroupLock)
            {
                ViewSourceGroup sourceGroup;
                if (Groups.ContainsKey(groupName))
                {
                    sourceGroup = Groups[groupName];
                }
                else
                {
                    sourceGroup = new ViewSourceGroup();
                    Groups.Add(groupName, sourceGroup);
                }
                sourceGroup.Add(viewSource);
            }
        }

        public static void Clear()
        {
            lock (GroupLock)
            {
                Groups.Clear();
            }
        }

        public static void Sort(string groupName, string propertyName, ListSortDirection direction)
        {
            lock (GroupLock)
            {
                if (!Groups.ContainsKey(groupName)) return;
                Groups[groupName].UpdateSortDescriptor(propertyName, direction);
            }
        }

        public static void ToggleSortation(string groupName, string propertyName)
        {
            lock (GroupLock)
            {
                if (!Groups.ContainsKey(groupName)) return;
                var sourceGroup = Groups[groupName];
                var direction = sourceGroup.SortDirection;
                sourceGroup.UpdateSortDescriptor(propertyName, direction == null ? ListSortDirection.Ascending : (direction == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending));
            }
        }

        private void Add(CollectionViewSource viewSource)
        {
            lock (_viewSourcesLock)
            {
                bool alreadyPresent = false;
                for (int i = _collectionViewSources.Count - 1; i > -1; i--)
                {
                    var weakReference = _collectionViewSources[i];
                    if (!weakReference.IsAlive)
                    {
                        _collectionViewSources.RemoveAt(i);
                        continue;
                    }
                    if (Equals(weakReference.Target, viewSource))
                    {
                        alreadyPresent = true;
                        continue;
                    }
                }
                if (alreadyPresent) return;
                _collectionViewSources.Add(new WeakReference(viewSource));
            }
        }

        private void UpdateSortDescriptor(string propertyName, ListSortDirection direction)
        {
            lock (_viewSourcesLock)
            {
                for (int i = _collectionViewSources.Count - 1; i > -1; i--)
                {
                    var weakReference = _collectionViewSources[i];
                    if (weakReference.IsAlive)
                    {
                        var viewSource = (CollectionViewSource)weakReference.Target;
                        viewSource.SortDescriptions.Clear();
                        viewSource.SortDescriptions.Add(new SortDescription(propertyName, direction));
                    }
                }
            }
        }

        public int Count
        {
            get
            {
                lock (_viewSourcesLock)
                {
                    return _collectionViewSources.Count;
                }
            }
        }

        public CollectionViewSource this[int index]
        {
            get
            {
                lock (_viewSourcesLock)
                {
                    return (CollectionViewSource)_collectionViewSources[index].Target;
                }
            }
        }

        public ListSortDirection? SortDirection
        {
            get
            {
                lock (_viewSourcesLock)
                {
                    var firstOrDefault = _collectionViewSources.FirstOrDefault(x => x.IsAlive);
                    if (firstOrDefault == null) return null;
                    var viewSource = (CollectionViewSource)firstOrDefault.Target;
                    if (viewSource.SortDescriptions.Count == 0) return null;
                    return viewSource.SortDescriptions[0].Direction;
                }
            }
        }

        private readonly IList<WeakReference> _collectionViewSources = new List<WeakReference>();
        private readonly object _viewSourcesLock = new object();

        private ViewSourceGroup()
        {

        }
    }
}
